package com.cxx.purchasecharge.component.controller;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cxx.purchasecharge.component.bean.ActionResult;
import com.cxx.purchasecharge.component.bean.ActionResult.ActionResultStatus;
import com.cxx.purchasecharge.component.bean.BaseBean;
import com.cxx.purchasecharge.component.bean.DataGridRequestForm;
import com.cxx.purchasecharge.component.bean.GenericPagingResult;
import com.cxx.purchasecharge.component.bean.GoodsBean;
import com.cxx.purchasecharge.component.bean.LoginUser;
import com.cxx.purchasecharge.component.bean.PCApplicationContext;
import com.cxx.purchasecharge.component.utils.AjaxUtils;
import com.cxx.purchasecharge.component.utils.BeanConvertUtils;
import com.cxx.purchasecharge.component.utils.ComponentConstants;
import com.cxx.purchasecharge.component.utils.MessageProperties;
import com.cxx.purchasecharge.core.model.persistence.Goods;
import com.cxx.purchasecharge.core.model.persistence.GoodsStorage;
import com.cxx.purchasecharge.core.model.persistence.GoodsType;
import com.cxx.purchasecharge.dal.GoodsDao;
import com.cxx.purchasecharge.dal.GoodsStorageDao;
import com.cxx.purchasecharge.dal.GoodsTypeDao;
import com.cxx.purchasecharge.service.PersistenceService;
import com.cxx.purchasecharge.service.QueryService;

@Controller
@RequestMapping ("/goods")
public class GoodsManager extends GenericController <GoodsBean>
{
    private static final Logger logger = Logger.getLogger (GoodsManager.class);

    @Autowired
    private GoodsDao goodsDao;
    @Autowired
    private GoodsTypeDao goodsTypeDao;
    @Autowired
    private GoodsStorageDao storageDao;
    @Autowired
    private QueryService queryService;
    @Autowired
    private PersistenceService persistenceService;
    @Autowired
    private PCApplicationContext pcContext;

    public GoodsManager ()
    {
        super.setViewName("goodsManagement");
    }

    @Override
    public String checkExist(@RequestParam String goodsId, @RequestParam String name, HttpServletRequest request)
    {
        if (StringUtils.isBlank (goodsId))
        {
            // new
            Goods obj = goodsDao.findByName (name);
            if (null != obj)
            {
                return "false";
            }
        }
        else
        {
            // edit
            long id = Long.parseLong (goodsId);
            Goods goods = goodsDao.findByName (name);
            if (null != goods && goods.getId () != id)
            {
                return "false";
            }
        }

        return "true";
    }

    @Override
    public String getAllModel(DataGridRequestForm dataGridRequestForm, HttpServletRequest request)
    {
        List <Goods> allGoods = (List <Goods>) goodsDao.findAll ();
        JSONArray jsonObject = JSONArray.fromObject (BeanConvertUtils.goodsList2GoodsBeanList (allGoods));
        return jsonObject.toString ();
    }
    
    @RequestMapping(value = "/getGoodsByNameLike", method = RequestMethod.POST)
    public void getGoodsByNameLike(@RequestParam String name, HttpServletResponse response) throws Exception
    {
        logger.debug (name);
        if(StringUtils.isNotBlank (name)) 
        {
            response.setContentType ("text/html;charset=utf-8");
            PrintWriter writer = response.getWriter ();
            
            List <Goods> goodsList = (List <Goods>) goodsDao.findByFuzzyName (name);
            JSONArray jsonObject = JSONArray.fromObject (BeanConvertUtils.goodsList2GoodsBeanList (goodsList));
            writer.write ("flightHandler(" + jsonObject.toString() + ")");
        }
    }

    @Override
    public String addModel(GoodsBean bean, BindingResult bindingResult, HttpServletRequest request)
    {
        if (bindingResult.hasErrors ())
        {
            logger.error (bindingResult.getAllErrors ());
            ActionResult ar = ActionResult.badRequest ()
                                          .withMessage (MessageProperties.getConfig (ComponentConstants.GENERIC_MSG_REQUEST_ARGS_ERROR))
                                          .build ();
            return AjaxUtils.getJsonObject (ar);
        }
        else
        {
            ActionResult ar = ActionResult.createActionResult ().build ();
            try
            {
                String user = pcContext.getLoginUser (request).getUserId ();
                Goods goods = goodsDao.save (BeanConvertUtils.goodsBean2Goods (bean));
                GoodsStorage storage = new GoodsStorage ();
                storage.setGoods (goods);
                storage.setCreateDate (new Date ());
                storage.setLastUpdated (new Date ());
                storage.setUserCreatedBy(queryService.getUniqueIdByUserId(user));
                storage.setUserUpdatedBy(queryService.getUniqueIdByUserId(user));
                if (null != bean.getStorageBean ())
                {
                    storage.setCurrentStock (bean.getStorageBean ().getInitialStock ());
                    storage.setInitialStock (bean.getStorageBean ().getInitialStock ());
                    storage.setMinStock (bean.getStorageBean ().getMinStock ());
                    storage.setMaxStock (bean.getStorageBean ().getMaxStock ());
                }
                storageDao.save (storage);
                ar = ActionResult.ok ()
                                 .withMessage (MessageProperties.getConfigFormatted (ComponentConstants.GENERIC_MSG_ADD_SUCCESS,
                                                                                     ComponentConstants.MSG_GOODS))
                                 .build ();
            }
            catch (Exception e)
            {
                logger.error (e.getMessage (), e);
                ar = ActionResult.serverError ()
                                 .withMessage (MessageProperties.getConfigFormatted (ComponentConstants.GENERIC_MSG_ADD_FAIL,
                                                                                     ComponentConstants.MSG_GOODS))
                                 .build ();
            }
            return AjaxUtils.getJsonObject (ar);
        }
    }

    @Override
    public String updateModel(GoodsBean bean, BindingResult bindingResult, HttpServletRequest request)
    {
        if (bindingResult.hasErrors ())
        {
            logger.error (bindingResult.getAllErrors ());
            ActionResult ar = ActionResult.badRequest ()
                                          .withMessage (MessageProperties.getConfig (ComponentConstants.GENERIC_MSG_REQUEST_ARGS_ERROR))
                                          .build ();
            return AjaxUtils.getJsonObject (ar);
        }
        else
        {
            ActionResult ar = ActionResult.createActionResult ().build ();
            try
            {
                goodsDao.save (BeanConvertUtils.goodsBean2Goods (bean));
                ar = ActionResult.ok ()
                                 .withMessage (MessageProperties.getConfigFormatted (ComponentConstants.GENERIC_MSG_UPDATE_SUCCESS,
                                                                                     ComponentConstants.MSG_GOODS))
                                 .build ();
            }
            catch (Exception e)
            {
                logger.error (e.getMessage (), e);
                ar = ActionResult.serverError ()
                                 .withMessage (MessageProperties.getConfigFormatted (ComponentConstants.GENERIC_MSG_UPDATE_FAIL,
                                                                                     ComponentConstants.MSG_GOODS))
                                 .build ();
            }
            return AjaxUtils.getJsonObject (ar);
        }
    }

    @Override
    public String deleteModel(@RequestParam String id, HttpServletRequest request)
    {
        if (StringUtils.isNotBlank (id))
        {
            Goods goods;
            goods = new Goods ();
            goods.setId (Long.parseLong (id));

            ActionResult ar = ActionResult.createActionResult ().build ();
            try
            {
                LoginUser loginUser = pcContext.getLoginUser (request);
                String operator = loginUser.getUserId ();
                StringBuilder sb = new StringBuilder ();
                if (CollectionUtils.isNotEmpty (queryService.getOrderItemByGoods (goods.getId ())))
                {
                    sb.append (goods.getId () + ",");
                }
                else
                {
                    persistenceService.deleteGoods (goods);
                }
                ar = ActionResult.ok ()
                                 .withMessage (MessageProperties.getConfigFormatted (ComponentConstants.GENERIC_MSG_DELETE_SUCCESS,
                                                                                     ComponentConstants.MSG_GOODS))
                                 .build ();
            }
            catch (Exception e)
            {
                logger.error (e.getMessage (), e);
                ar = ActionResult.serverError ()
                                 .withMessage (MessageProperties.getConfigFormatted (ComponentConstants.GENERIC_MSG_DELETE_FAIL,
                                                                                     ComponentConstants.MSG_GOODS))
                                 .build ();
            }
            return AjaxUtils.getJsonObject (ar);
        }
        else
        {
            logger.error (ActionResultStatus.BAD_REQUEST);
            ActionResult ar = ActionResult.badRequest ()
                                          .withMessage (MessageProperties.getConfig (ComponentConstants.GENERIC_MSG_REQUEST_ARGS_ERROR))
                                          .build ();
            return AjaxUtils.getJsonObject (ar);
        }
    }

    @Override
    public String deleteModels(@RequestParam String ids, HttpServletRequest request)
    {
        if (null != ids && ids.trim ().length () > 0)
        {
            List <Goods> goodses = new ArrayList <Goods> ();
            Goods goods;
            if (ids.indexOf (";") != -1)
            {
                String[] idArr = ids.split (";");
                for (String typeId : idArr)
                {
                    goods = new Goods ();
                    goods.setId (Long.parseLong (typeId));
                    goodses.add (goods);
                }
            }
            else
            {
                goods = new Goods ();
                goods.setId (Long.parseLong (ids));
                goodses.add (goods);
            }

            ActionResult ar = ActionResult.createActionResult ().build ();
            try
            {
                goodsDao.delete (goodses);
                ar = ActionResult.ok ()
                                 .withMessage (MessageProperties.getConfigFormatted (ComponentConstants.GENERIC_MSG_DELETE_SUCCESS,
                                                                                     ComponentConstants.MSG_GOODS))
                                 .build ();
            }
            catch (Exception e)
            {
                logger.error (e.getMessage (), e);
                ar = ActionResult.serverError ()
                                 .withMessage (MessageProperties.getConfigFormatted (ComponentConstants.GENERIC_MSG_DELETE_FAIL,
                                                                                     ComponentConstants.MSG_GOODS))
                                 .build ();
            }
            return AjaxUtils.getJsonObject (ar);
        }
        else
        {
            logger.error (ActionResultStatus.BAD_REQUEST);
            ActionResult ar = ActionResult.badRequest ()
                                          .withMessage (MessageProperties.getConfig (ComponentConstants.GENERIC_MSG_REQUEST_ARGS_ERROR))
                                          .build ();
            return AjaxUtils.getJsonObject (ar);
        }
    }

    /*@RequestMapping (value = "/getGoods", method = RequestMethod.POST)
    public @ResponseBody
    String getGoods (DataGridRequestForm dataGridRequestForm)
    {
        logger.debug (dataGridRequestForm);

        List <GoodsBean> goodsBeans = new ArrayList <GoodsBean> ();
        List <Goods> goodsList = (List <Goods>) goodsDao.findAll ();
        if (CollectionUtils.isNotEmpty (goodsList))
        {
            List <GoodsType> goodsTypes = (List <GoodsType>) goodsTypeDao.findAll ();
            if (CollectionUtils.isNotEmpty (goodsTypes))
            {
                for (GoodsType goodsType : goodsTypes)
                {
                    if (null != goodsType && null == goodsType.getParent ())
                    {
                        goodsBeans.add (goodsType2GoodsBean (goodsType));
                    }
                }
            }

            for (Goods goods : goodsList)
            {
                if (null == goods.getType ())
                {
                    goodsBeans.add (BeanConvertUtils.goods2GoodsBean (goods));
                }
            }
        }

        JSONArray jsonArray = JSONArray.fromObject (goodsBeans);
        return jsonArray.toString ();
    }*/
    
    @RequestMapping (value = "/asyncGetGoods", method = RequestMethod.POST)
    public @ResponseBody
    String asyncGetGoods (BaseBean baseBean, String searchKey)
    {
        if(StringUtils.isNotBlank(searchKey)) 
        {
            GenericPagingResult <GoodsBean> goodsPagingResult = new GenericPagingResult <GoodsBean> ();
            List <GoodsBean> goodsBeans = new ArrayList <GoodsBean> ();
            List <Goods> goodses = goodsDao.findByFuzzyName(searchKey);
            List <Goods> goodsResult = new ArrayList <Goods> ();
            for(Goods goods : goodses) 
            {
                Goods newGoods = new Goods ();
                try
                {
                    newGoods = (Goods)BeanUtils.cloneBean (goods);
                }
                catch (Exception e)
                {
                    // TODO 
                }
                Goods dbGoods = goodsDao.findOne (goods.getId ());
                newGoods.setUnit (dbGoods.getUnit ());
                newGoods.setType (dbGoods.getType ());
                newGoods.setDepository(dbGoods.getDepository());
                goodsResult.add (newGoods);
            }
            goodsBeans.addAll (BeanConvertUtils.goodsList2GoodsBeanList(goodsResult));
            goodsPagingResult.setRows (goodsBeans);
            long count = goodsBeans.size();
            goodsPagingResult.setTotal (count);
            List<Map <String, String>> footer = new ArrayList <Map<String,String>> ();
            Map<String, String> map = new HashMap <String, String> ();
            map.put ("iconCls", "icon-sum");
            map.put ("name", "货物合计：" + count);
            footer.add (map);
            goodsPagingResult.setFooter (footer);
            JSONObject jsonObject = JSONObject.fromObject (goodsPagingResult);
            return jsonObject.toString ();
        }
        
        List <GoodsBean> goodsBeans = new ArrayList <GoodsBean> ();
        if(StringUtils.isBlank (baseBean.getId ())) 
        {
            List <Goods> goodsList = (List <Goods>) goodsDao.findAll ();
            if (CollectionUtils.isNotEmpty (goodsList))
            {
                for (Goods goods : goodsList)
                {
                    if (null == goods.getType ())
                    {
                        goodsBeans.add (BeanConvertUtils.goods2GoodsBean (goods));
                    }
                }
                
                List <GoodsType> goodsTypes = (List <GoodsType>) goodsTypeDao.findAll ();
                if (CollectionUtils.isNotEmpty (goodsTypes))
                {
                    for (GoodsType goodsType : goodsTypes)
                    {
                        if (null != goodsType && null == goodsType.getParent ())
                        {
                            goodsBeans.add (goodsType2GoodsBean2 (goodsType));
                        }
                    }
                }
            }
            
            GenericPagingResult <GoodsBean> goodsPagingResult = new GenericPagingResult <GoodsBean> ();
            goodsPagingResult.setRows (goodsBeans);
            long count = goodsDao.count ();
            goodsPagingResult.setTotal (count);
            List<Map <String, String>> footer = new ArrayList <Map<String,String>> ();
            Map<String, String> map = new HashMap <String, String> ();
            map.put ("iconCls", "icon-sum");
            map.put ("name", "货物合计：" + count);
            footer.add (map);
            goodsPagingResult.setFooter (footer);
            JSONObject jsonObject = JSONObject.fromObject (goodsPagingResult);
            return jsonObject.toString ();
        }
        else 
        {
            List<GoodsType> goodsTypes = goodsTypeDao.findByParent(Long.parseLong (baseBean.getId ()));
            if(CollectionUtils.isNotEmpty(goodsTypes)) 
            {
                for(GoodsType goodsType : goodsTypes) 
                {
                    goodsBeans.add(goodsType2SingleGoodsBean (goodsType));
                }
            }
            
            GoodsType goodsType = new GoodsType();
            goodsType.setId(Long.parseLong (baseBean.getId ()));
            List<Goods> goodses = goodsDao.findByType(goodsType);
            if(CollectionUtils.isNotEmpty (goodses)) 
            {
                for(Goods goods : goodses) 
                {
                    goodsBeans.add (BeanConvertUtils.goods2GoodsBean (goods));
                }
            }
            JSONArray jsonArray = JSONArray.fromObject (goodsBeans);
            return jsonArray.toString ();
        }
    }
    
    /*@RequestMapping (value = "/asyncGetGoods", method = RequestMethod.POST)
    public @ResponseBody
    String asyncGetGoods (BaseBean baseBean)
    {
        List <GoodsBean> goodsBeans = new ArrayList <GoodsBean> ();
        if(StringUtils.isBlank (baseBean.getId ())) 
        {
            List <Goods> goodsList = (List <Goods>) goodsDao.findAll ();
            if (CollectionUtils.isNotEmpty (goodsList))
            {
                List <GoodsType> goodsTypes = (List <GoodsType>) goodsTypeDao.findAll ();
                if (CollectionUtils.isNotEmpty (goodsTypes))
                {
                    for (GoodsType goodsType : goodsTypes)
                    {
                        if (null != goodsType && null == goodsType.getParent ())
                        {
                            goodsBeans.add (goodsType2GoodsBean (goodsType));
                        }
                    }
                }
                
                for (Goods goods : goodsList)
                {
                    if (null == goods.getType ())
                    {
                        goodsBeans.add (BeanConvertUtils.goods2GoodsBean (goods));
                    }
                }
            }
        }
        else 
        {
            List<GoodsType> goodsTypes = goodsTypeDao.findByParent (Long.parseLong (baseBean.getId ()));
            if(CollectionUtils.isNotEmpty (goodsTypes)) 
            {
                for(GoodsType goodsType : goodsTypes) 
                {
                    goodsBeans.add (goodsType2GoodsBean (goodsType));
                }
            }
        }
        
        JSONArray jsonArray = JSONArray.fromObject (goodsBeans);
        return jsonArray.toString ();
    }*/

    private GoodsBean goodsType2GoodsBean (GoodsType goodsType)
    {
        GoodsBean goodsBean = new GoodsBean ();
        if (null != goodsType.getParent ())
        {
            goodsBean.setId (goodsType.getId () + "");
            goodsBean.setName (goodsType.getName ());
            goodsBean.setGoods (false);

            List <Goods> goodsList = goodsDao.findByType (goodsType);
            List <GoodsBean> children = new ArrayList <GoodsBean> ();
            if (CollectionUtils.isNotEmpty (goodsList))
            {
                children.addAll (BeanConvertUtils.goodsList2GoodsBeanList (goodsList));
            }

            List <GoodsType> goodsTypes = goodsTypeDao.findByParent (goodsType.getId ());
            if (CollectionUtils.isNotEmpty (goodsTypes))
            {
                for (GoodsType gt : goodsTypes)
                {
                    children.add (goodsType2GoodsBean (gt));
                }
            }
            goodsBean.setChildren (children);
        }
        else
        {
            goodsBean.setId (goodsType.getId () + "");
            goodsBean.setName (goodsType.getName ());
            goodsBean.setGoods (false);

            List <Goods> goodsList = goodsDao.findByType (goodsType);
            List <GoodsBean> children = new ArrayList <GoodsBean> ();
            if (CollectionUtils.isNotEmpty (goodsList))
            {
                children.addAll (BeanConvertUtils.goodsList2GoodsBeanList (goodsList));
            }

            List <GoodsType> goodsTypes = goodsTypeDao.findByParent (goodsType.getId ());
            if (CollectionUtils.isNotEmpty (goodsTypes))
            {
                for (GoodsType gt : goodsTypes)
                {
                    children.add (goodsType2GoodsBean (gt));
                }
            }
            goodsBean.setChildren (children);
        }
        return goodsBean;
    }
    
    private GoodsBean goodsType2SingleGoodsBean (GoodsType goodsType)
    {
        if(null != goodsType) 
        {
            GoodsBean goodsBean = new GoodsBean();
            goodsBean.setGoods(false);
            goodsBean.setId(goodsType.getId() + "");
            goodsBean.setName(goodsType.getName());
            List<Goods> goodses = goodsDao.findByType(goodsType);
            if(CollectionUtils.isEmpty (goodses)) 
            {
                goodsBean.setState ("open");
            }
            
            return goodsBean;
        }
        return null;
    }
    
    private GoodsBean goodsType2GoodsBean2 (GoodsType goodsType)
    {
        GoodsBean goodsBean = new GoodsBean ();
        if (null != goodsType.getParent ())
        {
            goodsBean.setId (goodsType.getId () + "");
            goodsBean.setName (goodsType.getName ());
            goodsBean.setGoods(false);
            List<Goods> goodses = goodsDao.findByType(goodsType);
            if(CollectionUtils.isEmpty (goodses)) 
            {
                goodsBean.setState ("open");
                List <GoodsBean> children = new ArrayList <GoodsBean> ();
                List <GoodsType> list = goodsTypeDao.findByParent (goodsType.getId ());
                if(CollectionUtils.isNotEmpty (list)) 
                {
                    for (GoodsType type : list)
                    {
                        children.add (goodsType2GoodsBean2 (type));
                    }
                }
                goodsBean.setChildren (children);
            }
        }
        else
        {
            goodsBean.setId (goodsType.getId () + "");
            goodsBean.setName (goodsType.getName ());
            goodsBean.setGoods(false);
            List<Goods> goodses = goodsDao.findByType(goodsType);
            if(CollectionUtils.isEmpty (goodses)) 
            {
                goodsBean.setState ("open");
                List <GoodsBean> children = new ArrayList <GoodsBean> ();
                List <GoodsType> list = goodsTypeDao.findByParent (goodsType.getId ());
                if(CollectionUtils.isNotEmpty (list)) 
                {
                    for (GoodsType type : list)
                    {
                        children.add (goodsType2GoodsBean2 (type));
                    }
                }
                goodsBean.setChildren (children);
            }
        }
        
        return goodsBean;
    }

}
